
from yacf.Frontend.C99 import c99_ast

from yacf.Backends.C99.Writers.C99Writer import CWriter

class AccWriter(CWriter):
    """ Visitor which translates the IR to C99/OpenAcc.

    """

    def _write_acc_region(self, node, offset):
        self.write_blank();
        self.write(offset, node.name)
        self.write_blank();
        if node.clauses:
#            print "  Region " + str(node.name)  + " contains clauses "
            for elem in node.clauses:
#                print " Calling to visit_" + str(elem.__class__)
                self.visit(elem)
                self.write_blank();
        if node.stmt:
            self.writeLn(offset, "")
            self.visit(node.stmt)
        self.write_blank();

    def visit_AccParallel(self, node, offset):
        self._write_acc_region(node, offset);
        
    def visit_AccKernels(self, node, offset):
        self._write_acc_region(node, offset);
 
    def visit_AccData(self, node, offset):
        self._write_acc_region(node, offset);

      
        
    def visit_AccLoop(self, node, offset):
        self.write_blank();
        self.write(offset, node.name)
        self.write_blank();
        if node.clauses:
            for elem in node.clauses:
                self.visit(elem)
                self.write_blank();

        self.write_blank();
        # AccFor always has an stmt 
        if node.stmt:
            self.writeLn(offset, " ")
            self.visit(node.stmt)
        self.write_blank();  

    def visit_AccSyncronization(self, node, offset):
        self.write_blank();
        self.write(offset, node.name)

    def visit_AccWait(self, node, offset):
        self.write_blank();
        self.write(offset, node.name)
        if node.value:
            self.visit(offset, node.value)


    def visit_AccParallelOption(self, node, offset):
        self.write(offset, node.name.lower())
        self.write(0, '(');
        self.visit(node.value)
        self.write(0, ')');

    def visit_AccClause(self, node, offset):
        self.write(offset, node.name.lower())
        # TODO: Fix reduction parenthesis error
        if node.name == 'REDUCTION':
            self.write(0, '(');
            self.write(0, node.type)
            self.write(0, ':')

        if node.identifiers:
	        self.visit_ParamList(node.identifiers, enclosing=not (node.name == 'REDUCTION'))

        if node.name == 'REDUCTION':
            self.write(0, ')');
    
    ############################ Acc nodes

#    def visit_AccRegion(self, node, offset):
#        self.write_blank();
#        self.write(offset, node.name)
#        self.write_blank();
#        # self.write(offset, 'parallel')
#        # self.write_blank();
#        if node.clauses:
#            for elem in node.clauses:
#                self.visit(elem)
#                self.write_blank();
#        if node.stmt:
#            self.writeLn(offset, "")
#            self.visit(node.stmt)
#        self.write_blank();
#


    def visit_AccName(self, node, offset):
        self.write_blank();
        self.write(offset, "name( \"")
        self.write(offset, node.label)
        self.write(offset, "\")")
 
    def _write_copy_clause(self, node, offset):
        self.write_blank();
        self.write(offset, node.name.lower() +"(");
        if node.identifiers:
	        self.visit_ParamList(node.identifiers, enclosing=False)

        self.write(offset, ")")

    def visit_AccCopyin(self, node, offset):
        self._write_copy_clause(node, offset)
    
    def visit_AccCopyout(self, node, offset):
        self._write_copy_clause(node, offset)
 
    def visit_AccCopy(self, node, offset):
        self._write_copy_clause(node, offset)

    def visit_AccCreate(self, node, offset):
        self._write_copy_clause(node, offset)

    def visit_AccIgnore(self, node, offset):
        self.write(offset, node.code[13:-13])

